# -*- coding: utf-8 -*-
# ---

require 'fileutils'
require 'rspec'

class String

  def squish
    dup.squish!
  end

  def squish!
    strip!
    gsub!(/\s+/, ' ')
    self
  end

end

module FundlerUtils

  def self.included(base)
    # ...
  end

end

module ExitCodeMatchers
  RSpec::Matchers.define :exit_with_code do |code|
    actual = nil
    match do |block|
      begin
        block.call
      rescue SystemExit => e
        actual = e.status
      end
      actual and actual == code
    end
    failure_message_for_should do |block|
      "expected block to call exit(#{code}) but exit" +
        (actual.nil? ? ' not called' : "(#{actual}) was called")
    end
    failure_message_for_should_not do |block|
      "expected block not to call exit(#{code})"
    end
    description do
      "expect block to call exit(#{code})"
    end
  end
end # ExitCodeMatchers

=begin rdoc

== Schema
http://people.mozilla.org/~dietrich/places-erd.png

== References
http://stackoverflow.com/questions/464516/firefox-bookmarks-sqlite-structure
https://developer.mozilla.org/en-US/docs/Places
https://developer.mozilla.org/en-US/docs/Retrieving_part_of_the_bookmarks_tree
https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavBookmarksService
http://davidkoepi.wordpress.com/2010/11/27/firefoxforensics/

== Queries

select moz_places.url, moz_bookmarks.title 
from moz_places,moz_bookmarks 
where moz_places.id = moz_bookmarks.fk and moz_bookmarks.title != '';

select keyword,url 
from moz_keywords 
left join moz_bookmarks on (moz_keywords.id = keyword_id) 
left join moz_places on (fk = moz_places.id);

select moz_places.url, datetime((moz_historyvisits.visit_date/1000000), ‘unixepoch’, ‘localtime’), moz_historyvisits.visit_type 
from moz_places, moz_historyvisits 
where moz_historyvisits.place_id = moz_places.id 
order by moz_historyvisits.visit_date desc;
=end

module QueryConstants

  # all bookmarks
  BOOKMARKS_QUERY = <<-SQL
    SELECT DISTINCT
        moz_places.url AS url,
        moz_bookmarks.title AS title,
        moz_bookmarks.id AS id,
        moz_items_annos.content AS description
    FROM
        moz_places,
        moz_bookmarks,
        moz_items_annos,
        moz_anno_attributes
    WHERE
        moz_anno_attributes.name = 'bookmarkProperties/description' AND
        moz_items_annos.anno_attribute_id = moz_anno_attributes.id AND
        moz_items_annos.item_id = moz_bookmarks.id AND
        moz_places.id = moz_bookmarks.fk AND
        moz_places.id IN (
                SELECT DISTINCT fk 
                FROM moz_bookmarks
                WHERE parent IN (
                    SELECT moz_bookmarks.id
                    FROM moz_bookmarks, moz_bookmarks_roots
                    WHERE moz_bookmarks_roots.root_name = 'tags'
                    AND moz_bookmarks.parent = moz_bookmarks_roots.folder_id
                )
            )
    ORDER BY UPPER(moz_bookmarks.title) ASC
  SQL
  
  # tag.id|tag.title
  QUERY_FOR_TAGS = <<-SQL
    SELECT id, title FROM moz_bookmarks WHERE parent = 4;
  SQL
  
  # all bookmarks with the "given" tag.id
  QUERY_BY_TAG = <<-SQL
    SELECT moz_places.id, moz_places.url, moz_places.title, moz_bookmarks.parent    
    FROM moz_places    
    LEFT OUTER JOIN moz_bookmarks    
    ON moz_places.id = moz_bookmarks.fk    
    WHERE moz_bookmarks.parent = @tag_id;
  SQL

  # bookmark.id|bookmark.fk|bookmark.title
  # ...
  #=> 1933|1387|SQLite Home Page
  # ...
  QUERY_FOR_SIMPLE_BOOKMARKS = <<-SQL
    SELECT id,fk,title FROM moz_bookmarks WHERE parent = 2;
  SQL

  # select the link between bookmars and tags
  # fk_id = 1387
  #=> 1934|1387|1144
  QUERY_FOR_LINK = <<-SQL
    SELECT id,fk,parent FROM moz_bookmarks WHERE title is null AND fk = @fk_id;
  SQL

  # tag.id|tag.title
  # parent = 1144
  #=> 1144|coding
  QUERY_FOR_TAG_BY_ID = <<-SQL
    SELECT id, title FROM moz_bookmarks WHERE parent = 4 AND id = @parent;
  SQL

end # QueryConstants

module HashBookmarksUtil
  def sort_bookmarks_by(field)
    if [:tag, :tile].include?(field.intern) 
      self.sort_by do |key, value|
        value[field.intern]
      end
    else
      self
    end
  end
end # HashBookmarksUtil
